package com.cup.bddm.impala.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cup.bddm.impala.Constant;
import com.cup.bddm.impala.dao.StreetDao;
import com.cup.bddm.impala.po.MchntDailyTrans;
import com.cup.bddm.impala.po.StreetAppDailyTrans;
import com.cup.bddm.impala.po.StreetDailyTrans;
import com.cup.bddm.impala.po.StreetInfo;
import com.cup.bddm.impala.po.StreetMchntInfo;
import com.cup.bddm.impala.po.StreetMonthData;
import com.cup.bddm.impala.vo.MchntInterTopVo;
import com.cup.bddm.impala.vo.StreetAppListVo;
import com.cup.bddm.impala.vo.StreetDailyLiveMchntVo;
import com.cup.bddm.impala.vo.StreetInfoVo;
import com.cup.bddm.impala.vo.StreetMchntListVo;
import com.cup.bddm.impala.vo.StreetMonthDataVo;
import com.cup.bddm.impala.vo.StreetMonthTransVo;
import com.cup.bddm.impala.vo.StreetTransDistVo;
import com.cup.bddm.impala.vo.StreetTransInfoVo;
import com.cup.bddm.impala.vo.StreetUpdateVo;
import com.cup.bddm.impala.vo.TransDist;
import com.cup.bddm.util.DateUtil;

@Service
public class StreetService {

	static Logger logger = Logger.getLogger(StreetService.class);

	@Autowired
	private StreetDao streetDao;

	public StreetTransInfoVo getStreetTrans(String streetCd, String date) {
		logger.info("get street trans info detail,streetCd=" + streetCd + ",date=" + date);
		StreetTransInfoVo streetTransInfoVo = new StreetTransInfoVo();

		try {

			StreetDailyTrans dayTrans = streetDao.getStreetDailyTrans(streetCd, date, "all");
			streetTransInfoVo.setDay_trans(dayTrans);
			streetTransInfoVo.setState(Constant.SUCCESS);

		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetTransInfoVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetTransInfoVo.setState(Constant.INTER_ERROR);
		}
		return streetTransInfoVo;
	}

	public StreetInfoVo getStreetInfo(String streetCd) {
		logger.info("get street trans info detail,streetCd=" + streetCd);
		StreetInfoVo streetInfoVo = new StreetInfoVo();

		try {

			// 获取商户基本信息
			StreetInfo streetInfo = streetDao.getStreetInfo(streetCd);
			if (streetInfo == null) {
				streetInfoVo.setState(Constant.NOT_EXIST);
				return streetInfoVo;
			}
			streetInfoVo.setStreet_info(streetInfo);

			streetInfoVo.setState(Constant.SUCCESS);

		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetInfoVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetInfoVo.setState(Constant.INTER_ERROR);
		}

		return streetInfoVo;

	}

	public StreetTransDistVo getStreetTransByTransType(String streetCd, String date) {
		logger.info("get street trans distribute by trans type ,streetCd=" + streetCd + ",date=" + date);
		StreetTransDistVo streetTransDistVo = new StreetTransDistVo();

		if (StringUtils.isEmpty(streetCd)) {
			streetTransDistVo.setState(Constant.PARA_ERROR);
			return streetTransDistVo;
		}

		try {

			// 获取nfc/qrc/offline的交易信息
			Map<String, StreetDailyTrans> transTypeMap = streetDao.getStreetTransByTransType(streetCd, date);
			List<TransDist> trans_dist = new ArrayList<TransDist>();
			for (Map.Entry<String, StreetDailyTrans> entry : transTypeMap.entrySet()) {
				TransDist trans = new TransDist();
				trans.setName(entry.getKey());
				trans.setValue(entry.getValue().getTrans_count());
				trans_dist.add(trans);
			}

			streetTransDistVo.setTrans_dist(trans_dist);
			streetTransDistVo.setState(Constant.SUCCESS);

		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetTransDistVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetTransDistVo.setState(Constant.INTER_ERROR);
		}

		return streetTransDistVo;
	}

	public StreetTransDistVo getStreetTransByMchntType(String streetCd, String date) {
		logger.info("get street trans distribute by mchnt type ,streetCd=" + streetCd + ",date=" + date);
		StreetTransDistVo streetTransDistVo = new StreetTransDistVo();

		try {

			// 获取商户类型的交易信息
			Map<String, StreetDailyTrans> mchntTypeMap = streetDao.getStreetTransByMchntType(streetCd, date);
			List<TransDist> trans_dist = new ArrayList<TransDist>();
			for (Map.Entry<String, StreetDailyTrans> entry : mchntTypeMap.entrySet()) {
				TransDist trans = new TransDist();
				trans.setName(entry.getKey());
				trans.setValue(entry.getValue().getTrans_count());
				trans_dist.add(trans);
			}

			streetTransDistVo.setTrans_dist(trans_dist);
			streetTransDistVo.setState(Constant.SUCCESS);

		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetTransDistVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetTransDistVo.setState(Constant.INTER_ERROR);
		}

		return streetTransDistVo;
	}

	public StreetMonthTransVo getRecentMonthsTrans(String streetCd, String date) {
		logger.info("get street recent month trans ,streetCd=" + streetCd + ",date=" + date);
		StreetMonthTransVo streetMonthTransVo = new StreetMonthTransVo();

		try {

			List<String> monthList = DateUtil.getPreNMonthList(date.substring(0, 6), 6);
			// 获取每月交易数据
			List<StreetMonthData> monthTransList = streetDao.getRecentMonthsTrans(streetCd, date.substring(0, 6));

			List<StreetMonthDataVo> trans_dist = new ArrayList<StreetMonthDataVo>();
			StreetMonthDataVo trans = new StreetMonthDataVo();
			trans.setType("all");
			List<BigDecimal> transNums = new ArrayList<BigDecimal>();
			for (String month : monthList) {
				BigDecimal transNum = new BigDecimal("0");
				for (StreetMonthData monthTrans : monthTransList) {
					if (monthTrans.getMonth().equals(month)) {
						transNum = monthTrans.getCount();
					}
				}
				transNums.add(transNum);
			}

			trans.setMonth_values(transNums);
			trans_dist.add(trans);

			streetMonthTransVo.setMonth_list(monthList);
			streetMonthTransVo.setTp_list(trans_dist);
			streetMonthTransVo.setState(Constant.SUCCESS);

		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetMonthTransVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetMonthTransVo.setState(Constant.INTER_ERROR);
		}

		return streetMonthTransVo;
	}

	public StreetMonthTransVo getRecentMonthsTpTrans(String streetCd, String date) {
		logger.info("get street recent month trans by mchnt type,streetCd=" + streetCd + ",date=" + date);
		StreetMonthTransVo streetMonthTransVo = new StreetMonthTransVo();

		try {
			List<String> monthList = DateUtil.getPreNMonthList(date.substring(0, 6), 6);
			// 获取每种商户类型每月交易数据
			Map<String, List<StreetMonthData>> monthTpTransMap = streetDao.getRecentMonthsTpTrans(streetCd, date.substring(0, 6));
			List<StreetMonthDataVo> trans_dist = new ArrayList<StreetMonthDataVo>();

			for (Map.Entry<String, List<StreetMonthData>> entry : monthTpTransMap.entrySet()) {
				StreetMonthDataVo trans = new StreetMonthDataVo();
				trans.setType(entry.getKey());
				List<StreetMonthData> monthTransList = entry.getValue();
				List<BigDecimal> transNums = new ArrayList<BigDecimal>();
				for (String month : monthList) {
					BigDecimal transNum = new BigDecimal("0");
					for (StreetMonthData monthTrans : monthTransList) {
						if (monthTrans.getMonth().equals(month)) {
							transNum = monthTrans.getCount();
						}
					}
					transNums.add(transNum);
				}
				trans.setMonth_values(transNums);
				trans_dist.add(trans);
			}
			streetMonthTransVo.setMonth_list(monthList);
			streetMonthTransVo.setTp_list(trans_dist);
			streetMonthTransVo.setState(Constant.SUCCESS);

		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetMonthTransVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetMonthTransVo.setState(Constant.INTER_ERROR);
		}

		return streetMonthTransVo;
	}

	public StreetMonthTransVo getRecentMonthsActiveMchntNum(String streetCd, String date) {
		logger.info("get street recent month ActiveMchntNum ,streetCd=" + streetCd + ",date=" + date);

		StreetMonthTransVo streetMonthTransVo = new StreetMonthTransVo();
		try {

			List<String> monthList = DateUtil.getPreNMonthList(date.substring(0, 6), 6);
			// 获取每月活跃商户数据
			List<StreetMonthData> monthTransList = streetDao.getRecentMonthsActiveMchntNum(streetCd, date.substring(0, 6));

			List<StreetMonthDataVo> trans_dist = new ArrayList<StreetMonthDataVo>();
			StreetMonthDataVo trans = new StreetMonthDataVo();
			trans.setType("active_nm");
			List<BigDecimal> mchntNums = new ArrayList<BigDecimal>();
			for (String month : monthList) {
				BigDecimal mchntNum = new BigDecimal("0");
				for (StreetMonthData monthCounts : monthTransList) {
					if (monthCounts.getMonth().equals(month)) {
						mchntNum = monthCounts.getCount();
					}
				}
				mchntNums.add(mchntNum);
			}
			trans.setMonth_values(mchntNums);
			trans_dist.add(trans);

			streetMonthTransVo.setMonth_list(monthList);
			streetMonthTransVo.setTp_list(trans_dist);
			streetMonthTransVo.setState(Constant.SUCCESS);

		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetMonthTransVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetMonthTransVo.setState(Constant.INTER_ERROR);
		}

		return streetMonthTransVo;
	}

	public StreetDailyLiveMchntVo getLiveMchntNum(String streetCd, String date) {
		logger.info("get street recent daily live MchntNum ,streetCd=" + streetCd + ",date=" + date);
		StreetDailyLiveMchntVo streetDailyLiveMchntVo = new StreetDailyLiveMchntVo();

		try {

			List<String> dateList = DateUtil.getMonthPreDateList(date);
			// 获取当月每日活动商户数据
			Map<String, Integer> dailyLiveMchntNumMap = streetDao.getLiveMchntNum(streetCd, date.substring(0, 6));

			List<Integer> mchntNums = new ArrayList<Integer>();
			for (String date1 : dateList) {
				Integer mchntNum = 0;
				if (dailyLiveMchntNumMap.get(date1) != null) {
					mchntNum = dailyLiveMchntNumMap.get(date1);
				}
				mchntNums.add(mchntNum);
			}

			List<String> dayList = new ArrayList<String>();
			for (String date2 : dateList) {
				dayList.add(Integer.valueOf(date2.substring(6, 8)) + "");
			}
			streetDailyLiveMchntVo.setDay_list(dayList);
			streetDailyLiveMchntVo.setValue_list(mchntNums);
			streetDailyLiveMchntVo.setState(Constant.SUCCESS);

		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetDailyLiveMchntVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetDailyLiveMchntVo.setState(Constant.INTER_ERROR);
		}

		return streetDailyLiveMchntVo;
	}

	public StreetMchntListVo getTopFallMchnt(String streetCd, String type, String date) {
		logger.info("get street recent 7 day decline Mchnt ,streetCd=" + streetCd + ". type=" + type + ",date=" + date);
		StreetMchntListVo streetMchntListVo = new StreetMchntListVo();
		try {

			List<StreetMchntInfo> mchntList = streetDao.getTopFallMchnt(streetCd, date, type);
			if (mchntList.size() == 0) {
				streetMchntListVo.setState(Constant.NO_TRANS);
			} else {
				streetMchntListVo.setState(Constant.SUCCESS);
				streetMchntListVo.setMchnt_list(mchntList);
			}
		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetMchntListVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetMchntListVo.setState(Constant.INTER_ERROR);
		}

		return streetMchntListVo;
	}

	public StreetMchntListVo getLessThan5Mchnt(String streetCd, String type, String date) {
		logger.info("get street less then 5 Mchnt in this month,streetCd=" + streetCd + ". type=" + type + ",date=" + date);
		StreetMchntListVo streetMchntListVo = new StreetMchntListVo();
		try {

			List<StreetMchntInfo> mchntList = streetDao.getLessThan5Mchnt(streetCd, date, type);
			if (mchntList.size() == 0) {
				streetMchntListVo.setState(Constant.NO_TRANS);
			} else {
				streetMchntListVo.setState(Constant.SUCCESS);
				streetMchntListVo.setMchnt_list(mchntList);
			}
		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetMchntListVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetMchntListVo.setState(Constant.INTER_ERROR);
		}

		return streetMchntListVo;
	}

	public StreetAppListVo getSortedAppTrans(String streetCd, String date) {
		logger.info("get street APP list,streetCd=" + streetCd + ",date=" + date);
		StreetAppListVo streetAppListVo = new StreetAppListVo();
		try {

			List<StreetAppDailyTrans> curAppList = streetDao.getSortedAppTrans(streetCd, date);
			List<StreetAppDailyTrans> preAppList = streetDao.getSortedAppTrans(streetCd, DateUtil.getPreday(date));

			streetAppListVo.setCur_app_list(curAppList);
			streetAppListVo.setPre_app_list(preAppList);
			streetAppListVo.setState(Constant.SUCCESS);
		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetAppListVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetAppListVo.setState(Constant.INTER_ERROR);
		}

		return streetAppListVo;
	}

	public MchntInterTopVo getTop5Mchnt(String streetCd, String type, String date) {
		logger.info("get street TOP mchnt ,streetCd=" + streetCd + ",type=" + type + ",date=" + date);
		MchntInterTopVo mchntInterTopVo = new MchntInterTopVo();
		try {

			List<MchntDailyTrans> mchntList = streetDao.getTop5Mchnt(streetCd, type, date);
			mchntInterTopVo.setTop_merchant(mchntList);
			mchntInterTopVo.setState(Constant.SUCCESS);
		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			mchntInterTopVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			mchntInterTopVo.setState(Constant.INTER_ERROR);
		}

		return mchntInterTopVo;
	}

	public StreetUpdateVo updateStreets(List<StreetInfo> streets) {
		logger.info("insert street info.len=" + streets.size());
		StreetUpdateVo streetUpdateVo = new StreetUpdateVo();

		try {

			List<StreetInfo> streetList = streetDao.updateStreetInfo(streets);
			if (streetList.size() > 0) {
				logger.info("insert street info not all success");
				streetUpdateVo.setState(Constant.PART_SUCCESS);
				streetUpdateVo.setError_list(streetList);
			}
			if (streetList.size() == 0) {
				logger.info("insert street info success");
				streetUpdateVo.setState(Constant.SUCCESS);
			}

			if (streetList.size() == streets.size()) {
				logger.info("insert street info fail");
				streetUpdateVo.setState(Constant.INSERT_FAIL);
				streetUpdateVo.setError_list(streetList);
			}

		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetUpdateVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetUpdateVo.setState(Constant.INTER_ERROR);
		}
		return streetUpdateVo;
	}

	public StreetUpdateVo updateStreets_m(List<StreetInfo> streets) {
		logger.info("insert street info.len=" + streets.size());
		StreetUpdateVo streetUpdateVo = new StreetUpdateVo();

		try {

			List<StreetInfo> streetList = streetDao.updateStreetInfo_m(streets);
			if (streetList.size() > 0) {
				logger.info("insert street info not all success");
				streetUpdateVo.setState(Constant.PART_SUCCESS);
				streetUpdateVo.setError_list(streetList);
			}
			if (streetList.size() == 0) {
				logger.info("insert street info success");
				streetUpdateVo.setState(Constant.SUCCESS);
			}

			if (streetList.size() == streets.size()) {
				logger.info("insert street info fail");
				streetUpdateVo.setState(Constant.INSERT_FAIL);
				streetUpdateVo.setError_list(streetList);
			}

		} catch (RuntimeException e) {
			logger.error("internal sql error!", e);
			streetUpdateVo.setState(Constant.INTER_ERROR);

		} catch (Exception e) {
			logger.error("internal error!", e);
			streetUpdateVo.setState(Constant.INTER_ERROR);
		}
		return streetUpdateVo;
	}

	public String getMaxStreetCd(String biz_street_cd) {
		if (biz_street_cd != null && biz_street_cd.length() == 5) {
			biz_street_cd = biz_street_cd.toUpperCase();
			String maxStreetCd = streetDao.getMaxStreetCd(biz_street_cd);
			if (maxStreetCd == null) {
				maxStreetCd = "0001";
			} else {
				maxStreetCd = frontCompWithZore(Integer.parseInt(maxStreetCd) + 1, 4);
			}
			return biz_street_cd + maxStreetCd;
		} else {
			return null;
		}
	}

	/**
	 * 将元数据前补零，补后的总长度为指定的长度，以字符串的形式返回
	 * 
	 * @param sourceDate
	 * @param formatLength
	 * @return 重组后的数据
	 */
	public static String frontCompWithZore(int sourceDate, int formatLength) {
		String newString = String.format("%0" + formatLength + "d", sourceDate);
		return newString;
	}
}
